import java.util.*;
class PrintKMoves {
  private static final char[] moves = {'R', 'D', 'L', 'U'};
  private static final Map<Character, int[]> directions = new HashMap<>();
  static {
    directions.put('R', new int[]{1, 0});
    directions.put('D', new int[]{0, 1});
    directions.put('L', new int[]{-1, 0});
    directions.put('U', new int[]{0, -1});
  }
  class Position {
      int x;
      int y;
      public Position(int x, int y) {
          this.x = x;
          this.y = y;
      }
      @Override
      public boolean equals(Object o) {
          if (this == o) return true;
          if (o == null || getClass() != o.getClass()) return false;
          Position position = (Position) o;
          return x == position.x &&
                 y == position.y;
      }
       @Override
        public int hashCode() {
            int result = x;
            result = 31 * result + y;
            return result;
        }
  }
    
  
  public List<String> printKMoves(int K) {
      List<String> result = new ArrayList<>();
      Set<Position> blackSet = new HashSet<>();
      int dir = 0;
      Position antPos = new Position(0, 0);
      // while (K > 0) {
      //     // 新的坐标对象用于放入集合
      //     Position t = new Position(antPos.x, antPos.y);
      //     // 如果黑块集合能存入，说明脚下的块不在集合中，也就意味着是白色，方向序号循环自增1
      //     if (blackSet.add(t)) dir = (dir + 1) % 4;
      //     else {
      //         // 否则说明脚下的块已经在集合中，也就意味着是黑色，方向序号循环自增3，相当于自减1，但是Math.floorMod取模可能消耗大？用+3替代
      //         dir = (dir + 3) % 4;
      //         // 别忘了删除，即将黑块变白
      //         blackSet.remove(t);
      //     }
      //     // 蚂蚁移动位置
      //     antPos.x += directions.get(moves[dir])[0];
      //     antPos.y += directions.get(moves[dir])[1];
      //     K--;
      // }


      for(int i = 0; i<K; i++){
        // 新的坐标对象用于放入集合
          Position t = new Position(antPos.x, antPos.y);

          boolean isBlack = blackSet.contains(t);
          dir = isBlack?  (dir + 3) % 4 : (dir + 1) % 4;
          if(isBlack){
            blackSet.remove(t);
          }else{
            blackSet.add(t);
          }
          // 蚂蚁移动位置
          antPos.x += directions.get(moves[dir])[0];
          antPos.y += directions.get(moves[dir])[1];
      }
      // 计算边界
      int left = antPos.x, right = antPos.x, top = antPos.y, bottom = antPos.y;
      for(Position p : blackSet){
        left = Math.min(left, p.x);
        right = Math.max(right, p.x);
        top = Math.min(top, p.y); 
        bottom = Math.max(bottom, p.y);
      }
   
      char[][] grid = new char[bottom - top + 1][right - left + 1];
        // 填充白块
        for (char[] row : grid)
            Arrays.fill(row, '_');
        // 替换黑块
        for (Position pos : blackSet)
            grid[pos.y - top][pos.x - left] = 'X';
        // 替换蚂蚁
        grid[antPos.y - top][antPos.x - left] = moves[dir];

      for(char[] row : grid){
        result.add(new String(row));
      }

      return result;
  }
  public static void main(String[] args) {
      PrintKMoves p = new PrintKMoves();
      List<String> moves = p.printKMoves(5);
      for (String move : moves) {
          System.out.println(move);
      }
  }
}

//  一只蚂蚁坐在由白色和黑色方格构成的无限网格上。开始时，网格全白，蚂蚁面向右侧。每行走一步，蚂蚁执行以下操作。

// (1) 如果在白色方格上，则翻转方格的颜色，向右(顺时针)转 90 度，并向前移动一个单位。
// (2) 如果在黑色方格上，则翻转方格的颜色，向左(逆时针方向)转 90 度，并向前移动一个单位。

// 编写程序来模拟蚂蚁执行的前 K 个动作，并返回最终的网格。

// 网格由数组表示，每个元素是一个字符串，代表网格中的一行，黑色方格由 'X' 表示，白色方格由 '_' 表示，蚂蚁所在的位置由 'L', 'U', 'R', 'D' 表示，
// 分别表示蚂蚁 左、上、右、下 的朝向。只需要返回能够包含蚂蚁走过的所有方格的最小矩形。

// 示例 1：

// 输入：0
// 输出：["R"]
// 示例 2：

// 输入：2
// 输出：
// [
//   "_X",
//   "LX"
// ]
// 示例 3：

// 输入：5
// 输出：
// [
//   "_U",
//   "X_",
//   "XX"
// ]